home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-06-05 | 57.0 KB | 2,015 lines |
- Newsgroups: comp.sources.misc
- From: daveg@csvax.caltech.edu (David Gillespie)
- Subject: v13i032: Emacs Calculator 1.01, part 06/19
- Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 13, Issue 32
- Submitted-by: daveg@csvax.caltech.edu (David Gillespie)
- Archive-name: gmcalc/part06
-
- ---- Cut Here and unpack ----
- #!/bin/sh
- # this is part 6 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- # file calc-ext.el continued
- #
- CurArch=6
- if test ! -r s2_seq_.tmp
- then echo "Please unpack part 1 first!"
- exit 1; fi
- ( read Scheck
- if test "$Scheck" != $CurArch
- then echo "Please unpack part $Scheck next!"
- exit 1;
- else exit 0; fi
- ) < s2_seq_.tmp || exit 1
- echo "x - Continuing file calc-ext.el"
- sed 's/^X//' << 'SHAR_EOF' >> calc-ext.el
- X (setq msgs (cons buf msgs)
- X buf "")
- X (calc-user-function-list kmap 6))
- X (if (/= flags 0)
- X (setq msgs (cons buf msgs)))
- X (calc-do-prefix-help (nreverse msgs) "user" ?z))
- X)
- X
- X(defun calc-user-function-classify (key)
- X (cond ((/= key (downcase key)) ; upper-case
- X (if (assq (downcase key) (calc-user-key-map)) 9 1))
- X ((/= key (upcase key)) 2) ; lower-case
- X ((= key ??) 0)
- X (t 4)) ; other
- X)
- X
- X(defun calc-user-function-list (map flags)
- X (and map
- X (let* ((key (car (car map)))
- X (kind (calc-user-function-classify key))
- X (func (cdr (car map))))
- X (if (= (logand kind flags) 0)
- X ()
- X (let* ((name (symbol-name func))
- X (name (if (string-match "\\`calc-" name)
- X (substring name 5) name))
- X (pos (string-match (char-to-string key) name))
- X (desc
- X (if (symbolp func)
- X (if (= (logand kind 3) 0)
- X (format "`%c' = %s" key name)
- X (if pos
- X (format "%s%c%s"
- X (downcase (substring name 0 pos))
- X (upcase key)
- X (downcase (substring name (1+ pos))))
- X (format "%c = %s"
- X (upcase key)
- X (downcase name))))
- X (char-to-string (upcase key)))))
- X (if (= (length buf) 0)
- X (setq buf (concat (if (= flags 1) "SHIFT + " "")
- X desc))
- X (if (> (+ (length buf) (length desc)) 58)
- X (setq msgs (cons buf msgs)
- X buf (concat (if (= flags 1) "SHIFT + " "")
- X desc))
- X (setq buf (concat buf ", " desc))))))
- X (calc-user-function-list (cdr map) flags)))
- X)
- X
- X
- X
- X(defun calc-shift-Z-prefix-help ()
- X (interactive)
- X (calc-do-prefix-help
- X '("Define, Undefine, Formula, Kbd-macro, Edit, Get-defn"
- X "Permanent; Var-perm"
- X "kbd-macros: [ (if), : (else), | (else-if), ] (end-if)"
- X "kbd-macros: < > (repeat), ( ) (for), { } (loop)"
- X "kbd-macros: / (break)"
- X "kbd-macros: ` (save), ' (restore)")
- X "user" ?Z)
- X)
- X
- X(defun calc-user-define ()
- X "Bind a Calculator command to a key sequence using the z prefix."
- X (interactive)
- X (message "Define user key: z-")
- X (let ((key (read-char)))
- X (if (= (calc-user-function-classify key) 0)
- X (error "Can't redefine \"?\" key"))
- X (let ((func (intern (completing-read (concat "Set key z "
- X (char-to-string key)
- X " to command: ")
- X obarray
- X 'commandp
- X t
- X "calc-"))))
- X (let* ((kmap (calc-user-key-map))
- X (old (assq key kmap)))
- X (if old
- X (setcdr old func)
- X (setcdr kmap (cons (cons key func) (cdr kmap)))))))
- X)
- X
- X(defun calc-user-undefine ()
- X "Remove the definition on a Calculator z prefix key."
- X (interactive)
- X (message "Undefine user key: z-")
- X (let ((key (read-char)))
- X (if (= (calc-user-function-classify key) 0)
- X (error "Can't undefine \"?\" key"))
- X (let* ((kmap (calc-user-key-map)))
- X (delq (or (assq key kmap)
- X (assq (upcase key) kmap)
- X (assq (downcase key) kmap)
- X (error "No such user key is defined"))
- X kmap)))
- X)
- X
- X(defun calc-user-define-formula ()
- X "Define a new Calculator z-prefix command using formula at top of stack."
- X (interactive)
- X (calc-wrapper
- X (let* ((form (calc-top 1))
- X (arglist nil)
- X odef key keyname cmd cmd-base func alist is-symb)
- X (calc-default-formula-arglist form)
- X (setq arglist (sort arglist 'string-lessp))
- X (message "Define user key: z-")
- X (setq key (read-char))
- X (if (= (calc-user-function-classify key) 0)
- X (error "Can't redefine \"?\" key"))
- X (setq key (and (not (memq key '(13 32))) key)
- X keyname (and key
- X (if (or (and (<= ?0 key) (<= key ?9))
- X (and (<= ?a key) (<= key ?z))
- X (and (<= ?A key) (<= key ?Z)))
- X (char-to-string key)
- X (format "%03d" key)))
- X odef (assq key (calc-user-key-map)))
- X (while
- X (progn
- X (setq cmd (completing-read "Define M-x command name: "
- X obarray 'commandp nil
- X (if (and odef (symbolp (cdr odef)))
- X (symbol-name (cdr odef))
- X "calc-"))
- X cmd-base (and (string-match "\\`calc-\\(.+\\)\\'" cmd)
- X (math-match-substring cmd 1))
- X cmd (and (not (or (string-equal cmd "")
- X (string-equal cmd "calc-")))
- X (intern cmd)))
- X (and cmd
- X (fboundp cmd)
- X odef
- X (not
- X (y-or-n-p
- X (if (get cmd 'calc-user-defn)
- X (concat "Replace previous definition for "
- X (symbol-name cmd) "? ")
- X "That name conflicts with a built-in Emacs function. Replace this function? "))))))
- X (if (and key (not cmd))
- X (setq cmd (intern (concat "calc-User-" keyname))))
- X (while
- X (progn
- X (setq func (completing-read "Define algebraic function name: "
- X obarray 'fboundp nil
- X (concat "calcFunc-"
- X (if cmd-base
- X (if (string-match
- X "\\`User-.+" cmd-base)
- X (concat
- X "User"
- X (substring cmd-base 5))
- X cmd-base)
- X "")))
- X func (and (not (or (string-equal func "")
- X (string-equal func "calcFunc-")))
- X (intern func)))
- X (and func
- X (fboundp func)
- X (not (fboundp cmd))
- X odef
- X (not
- X (y-or-n-p
- X (if (get func 'calc-user-defn)
- X (concat "Replace previous definition for "
- X (symbol-name func) "? ")
- X "That name conflicts with a built-in Emacs function. Replace this function? "))))))
- X (if (not func)
- X (setq func (intern (concat "calcFunc-User"
- X (or keyname
- X (and cmd (symbol-name cmd))
- X (format "%05d" (% (random) 10000)))))))
- X (while
- X (progn
- X (setq alist (read-from-minibuffer "Function argument list: "
- X (if arglist
- X (prin1-to-string arglist)
- X "()")
- X minibuffer-local-map
- X t))
- X (and (not (calc-subsetp alist arglist))
- X (y-or-n-p
- X "Okay for arguments that don't appear in formula to be ignored? "))))
- X (setq is-symb (and alist
- X func
- X (y-or-n-p
- X "Leave it symbolic for non-constant arguments? ")))
- X (if cmd
- X (progn
- X (fset cmd
- X (list 'lambda
- X '()
- X "User-defined Calculator function."
- X '(interactive)
- X (list 'calc-wrapper
- X (list 'calc-enter-result
- X (length alist)
- X (let ((name (symbol-name (or func cmd))))
- X (and (string-match
- X "\\([^-][^-]?[^-]?[^-]?\\)[^-]*\\'"
- X name)
- X (math-match-substring name 1)))
- X (list 'cons
- X (list 'quote func)
- X (list 'calc-top-list-n
- X (length alist)))))))
- X (put cmd 'calc-user-defn t)))
- X (let ((body (list 'math-normalize (calc-fix-user-formula form))))
- X (fset func
- X (append
- X (list 'lambda alist)
- X (and is-symb
- X (mapcar (function (lambda (v)
- X (list 'math-check-const v)))
- X alist))
- X (list body))))
- X (put func 'calc-user-defn form)
- X (if key
- X (let* ((kmap (calc-user-key-map))
- X (old (assq key kmap)))
- X (if old
- X (setcdr old cmd)
- X (setcdr kmap (cons (cons key cmd) (cdr kmap)))))))
- X (message ""))
- X)
- X
- X(defun calc-default-formula-arglist (form)
- X (if (consp form)
- X (if (eq (car form) 'var)
- X (if (or (memq (nth 1 form) arglist)
- X (boundp (nth 2 form)))
- X ()
- X (setq arglist (cons (nth 1 form) arglist)))
- X (calc-default-formula-arglist-step (cdr form))))
- X)
- X
- X(defun calc-default-formula-arglist-step (l)
- X (and l
- X (progn
- X (calc-default-formula-arglist (car l))
- X (calc-default-formula-arglist-step (cdr l))))
- X)
- X
- X(defun calc-subsetp (a b)
- X (or (null a)
- X (and (memq (car a) b)
- X (calc-subsetp (cdr a) b)))
- X)
- X
- X(defun calc-fix-user-formula (f)
- X (if (consp f)
- X (cond ((and (eq (car f) 'var)
- X (memq (nth 1 f) alist))
- X (nth 1 f))
- X ((math-constp f)
- X (list 'quote f))
- X (t
- X (cons 'list
- X (cons (list 'quote (car f))
- X (mapcar 'calc-fix-user-formula (cdr f))))))
- X f)
- X)
- X
- X
- X(defun calc-user-define-kbd-macro (arg)
- X "Bind the most recent keyboard macro to a key sequence using the z prefix."
- X (interactive "P")
- X (or last-kbd-macro
- X (error "No keyboard macro defined"))
- X (message "Define last kbd macro on user key: z-")
- X (let ((key (read-char)))
- X (if (= (calc-user-function-classify key) 0)
- X (error "Can't redefine \"?\" key"))
- X (let ((cmd (intern (completing-read "Full name for new command: "
- X obarray
- X 'commandp
- X nil
- X (concat "calc-User-"
- X (if (or (and (>= key ?a)
- X (<= key ?z))
- X (and (>= key ?A)
- X (<= key ?Z))
- X (and (>= key ?0)
- X (<= key ?9)))
- X (char-to-string key)
- X (format "%03d" key)))))))
- X (and (fboundp cmd)
- X (not (let ((f (symbol-function cmd)))
- X (or (stringp f)
- X (and (consp f)
- X (eq (car-safe (nth 3 f))
- X 'calc-execute-kbd-macro)))))
- X (error "Function %s is already defined and not a keyboard macro"
- X cmd))
- X (put cmd 'calc-user-defn t)
- X (fset cmd (if (< (prefix-numeric-value arg) 0)
- X last-kbd-macro
- X (list 'lambda
- X '(arg)
- X '(interactive "P")
- X (list 'calc-execute-kbd-macro
- X last-kbd-macro
- X 'arg))))
- X (let* ((kmap (calc-user-key-map))
- X (old (assq key kmap)))
- X (if old
- X (setcdr old cmd)
- X (setcdr kmap (cons (cons key cmd) (cdr kmap)))))))
- X)
- X
- X
- X(defun calc-user-define-edit (prefix)
- X "Edit the definition of a z-prefix command."
- X (interactive "P") ; but no calc-wrapper!
- X (message "Edit definition of command: z-")
- X (let* ((key (read-char))
- X (def (or (assq key (calc-user-key-map))
- X (assq (upcase key) (calc-user-key-map))
- X (assq (downcase key) (calc-user-key-map))
- X (error "No command defined for that key")))
- X (cmd (cdr def)))
- X (if (symbolp cmd)
- X (setq cmd (symbol-function cmd)))
- X (cond ((or (stringp cmd)
- X (and (consp cmd)
- X (eq (car-safe (nth 3 cmd)) 'calc-execute-kbd-macro)))
- X (if (and (>= (prefix-numeric-value prefix) 0)
- X (fboundp 'edit-kbd-macro)
- X (symbolp (cdr def))
- X (eq major-mode 'calc-mode))
- X (progn
- X (if (and (< (window-width) (screen-width))
- X calc-display-trail)
- X (let* ((trail (get-buffer-create "*Calc Trail*"))
- X (win (get-buffer-window trail)))
- X (if win
- X (delete-window win))))
- X (edit-kbd-macro (cdr def) prefix nil
- X (function
- X (lambda (x)
- X (and calc-display-trail
- X (calc-wrapper
- X (calc-trail-display 1 t)))))
- X (function
- X (lambda (cmd)
- X (if (stringp (symbol-function cmd))
- X (symbol-function cmd)
- X (nth 1 (nth 3 (symbol-function cmd))))))
- X (function
- X (lambda (new cmd)
- X (if (stringp (symbol-function cmd))
- X (fset cmd new)
- X (setcar (cdr (nth 3 (symbol-function
- X cmd)))
- X new))))))
- X (calc-wrapper
- X (calc-edit-mode (list 'calc-finish-macro-edit
- X (list 'quote def)))
- X (insert (if (stringp cmd)
- X cmd
- X (nth 1 (nth 3 cmd)))))
- X (calc-show-edit-buffer)))
- X (t (let* ((func (calc-stack-command-p cmd))
- X (defn (and func
- X (symbolp func)
- X (get func 'calc-user-defn))))
- X (if (and defn (calc-valid-formula-func func))
- X (progn
- X (calc-wrapper
- X (calc-edit-mode (list 'calc-finish-formula-edit
- X (list 'quote func)))
- X (insert (math-format-flat-expr defn 0) "\n"))
- X (calc-show-edit-buffer))
- X (error "That command's definition cannot be edited"))))))
- X)
- X
- X(defun calc-finish-macro-edit (def)
- X (let ((str (buffer-substring (point) (point-max))))
- X (if (symbolp (cdr def))
- X (if (stringp (symbol-function (cdr def)))
- X (fset (cdr def) str)
- X (setcar (cdr (nth 3 (symbol-function (cdr def)))) str))
- X (setcdr def str)))
- X)
- X
- X;;; The following are hooks into the MacEdit package from macedit.el.
- X(put 'calc-execute-extended-command 'MacEdit-print
- X (function (lambda ()
- X (setq macro-str (concat "\excalc-" macro-str))))
- X)
- X
- X(put 'calcDigit-start 'MacEdit-print
- X (function (lambda ()
- X (if calc-algebraic-mode
- X (calc-macro-edit-algebraic)
- X (MacEdit-unread-chars key-last)
- X (let ((str "")
- X (min-bsp 0)
- X ch last)
- X (while (and (setq ch (MacEdit-read-char))
- X (or (and (>= ch ?0) (<= ch ?9))
- X (memq ch '(?\. ?e ?\_ ?n ?\: ?\# ?M
- X ?o ?h ?\@ ?\"))
- X (and (memq ch '(?\' ?m ?s))
- X (string-match "[@oh]" str))
- X (and (or (and (>= ch ?a) (<= ch ?z))
- X (and (>= ch ?A) (<= ch ?Z)))
- X (string-match
- X "^[-+]?\\(1[1-9]\\|[2-9][0-9]\\)#"
- X str))
- X (and (memq ch '(?\177 ?\C-h))
- X (> (length str) 0))
- X (and (memq ch '(?+ ?-))
- X (> (length str) 0)
- X (eq (aref str (1- (length str)))
- X ?e))))
- X (if (or (and (>= ch ?0) (<= ch ?9))
- X (and (or (not (memq ch '(?\177 ?\C-h)))
- X (<= (length str) min-bsp))
- X (setq min-bsp (1+ (length str)))))
- X (setq str (concat str (char-to-string ch)))
- X (setq str (substring str 0 -1))))
- X (if (memq ch '(32 10 13))
- X (setq str (concat str (char-to-string ch)))
- X (MacEdit-unread-chars ch))
- X (insert "type \"")
- X (MacEdit-insert-string str)
- X (insert "\"\n")))))
- X)
- X
- X(defun calc-macro-edit-algebraic ()
- X (MacEdit-unread-chars key-last)
- X (let ((str "")
- X (min-bsp 0))
- X (while (progn
- X (MacEdit-lookup-key calc-alg-ent-map)
- X (or (and (memq key-symbol '(self-insert-command
- X calcAlg-previous))
- X (< (length str) 60))
- X (memq key-symbol
- X '(backward-delete-char
- X delete-backward-char
- X backward-delete-char-untabify))
- X (eq key-last 9)))
- X (setq macro-str (substring macro-str (length key-str)))
- X (if (or (eq key-symbol 'self-insert-command)
- X (and (or (not (memq key-symbol '(backward-delete-char
- X delete-backward-char
- X backward-delete-char-untabify)))
- X (<= (length str) min-bsp))
- X (setq min-bsp (+ (length str) (length key-str)))))
- X (setq str (concat str key-str))
- X (setq str (substring str 0 -1))))
- X (if (memq key-last '(10 13))
- X (setq str (concat str key-str)
- X macro-str (substring macro-str (length key-str))))
- X (if (> (length str) 0)
- X (progn
- X (insert "type \"")
- X (MacEdit-insert-string str)
- X (insert "\"\n"))))
- X)
- X(put 'calc-algebraic-entry 'MacEdit-print 'calc-macro-edit-algebraic)
- X(put 'calc-dollar-sign 'MacEdit-print 'calc-macro-edit-algebraic)
- X
- X(defun calc-macro-edit-variable ()
- X (let ((str "") ch)
- X (insert (symbol-name key-symbol) "\n")
- X (if (memq (MacEdit-peek-char) '(?\+ ?\- ?\* ?\/ ?\^ ?\|))
- X (setq str (char-to-string (MacEdit-read-char))))
- X (if (and (setq ch (MacEdit-peek-char))
- X (>= ch ?0) (<= ch ?9))
- X (insert "type \"" str
- X (char-to-string (MacEdit-read-char)) "\"\n")
- X (if (> (length str) 0)
- X (insert "type \"" str "\"\n"))
- X (MacEdit-read-argument)))
- X)
- X(put 'calc-store 'MacEdit-print 'calc-macro-edit-variable)
- X(put 'calc-recall 'MacEdit-print 'calc-macro-edit-variable)
- X(put 'calc-let 'MacEdit-print 'calc-macro-edit-variable)
- X
- X
- X(defun calc-finish-formula-edit (func)
- X (let ((buf (current-buffer))
- X (str (buffer-substring (point) (point-max)))
- X (start (point))
- X (body (calc-valid-formula-func func)))
- X (set-buffer calc-original-buffer)
- X (let ((val (math-read-expr str)))
- X (if (eq (car-safe val) 'error)
- X (progn
- X (set-buffer buf)
- X (goto-char (+ start (nth 1 val)))
- X (error (nth 2 val))))
- X (setcar (cdr body)
- X (let ((alist (nth 1 (symbol-function func))))
- X (calc-fix-user-formula val)))
- X (put func 'calc-user-defn val)))
- X)
- X
- X(defun calc-valid-formula-func (func)
- X (let ((def (symbol-function func)))
- X (and (consp def)
- X (eq (car def) 'lambda)
- X (progn
- X (setq def (cdr (cdr def)))
- X (while (and def
- X (not (eq (car (car def)) 'math-normalize)))
- X (setq def (cdr def)))
- X (car def))))
- X)
- X
- X
- X(defun calc-get-user-defn ()
- X "Extract the definition from a z-prefix command as a formula."
- X (interactive)
- X (calc-wrapper
- X (message "Get definition of command: z-")
- X (let* ((key (read-char))
- X (def (or (assq key (calc-user-key-map))
- X (assq (upcase key) (calc-user-key-map))
- X (assq (downcase key) (calc-user-key-map))
- X (error "No command defined for that key")))
- X (cmd (cdr def)))
- X (if (symbolp cmd)
- X (setq cmd (symbol-function cmd)))
- X (cond ((stringp cmd)
- X (message "Keyboard macro: %s" cmd))
- X (t (let* ((func (calc-stack-command-p cmd))
- X (defn (and func
- X (symbolp func)
- X (get func 'calc-user-defn))))
- X (if defn
- X (calc-enter-result 0 "gdef" defn)
- X (error "That command is not defined by a formula")))))))
- X)
- X
- X
- X(defun calc-user-define-permanent ()
- X "Make a user definition permanent by storing it in your .emacs file."
- X (interactive)
- X (calc-wrapper
- X (message "Record in %s the command: z-" calc-settings-file)
- X (let* ((key (read-char))
- X (def (or (assq key (calc-user-key-map))
- X (assq (upcase key) (calc-user-key-map))
- X (assq (downcase key) (calc-user-key-map))
- X (error "No command defined for that key"))))
- X (set-buffer (find-file-noselect (substitute-in-file-name
- X calc-settings-file)))
- X (goto-char (point-max))
- X (insert "\n;;; Definition stored by Calc on " (current-time-string)
- X "\n(setq calc-defs (append '(\n")
- X (let* ((cmd (cdr def))
- X (fcmd (and cmd (symbolp cmd) (symbol-function cmd)))
- X (pt (point))
- X (fill-column 70))
- X (if (and fcmd
- X (eq (car-safe fcmd) 'lambda)
- X (get cmd 'calc-user-defn))
- X (progn
- X (insert (prin1-to-string
- X (cons 'defun (cons cmd (cdr fcmd))))
- X "\n")
- X (fill-region pt (point))
- X (indent-rigidly pt (point) 3)
- X (delete-region pt (1+ pt))
- X (let* ((func (calc-stack-command-p cmd))
- X (ffunc (and func (symbolp func) (symbol-function func)))
- X (pt (point)))
- X (and ffunc
- X (eq (car-safe ffunc) 'lambda)
- X (get func 'calc-user-defn)
- X (progn
- X (insert (prin1-to-string
- X (cons 'defun (cons func (cdr ffunc))))
- X "\n")
- X (fill-region pt (point))
- X (indent-rigidly pt (point) 3)
- X (delete-region pt (1+ pt))))))
- X (and (stringp fcmd)
- X (insert " (fset '" (prin1-to-string cmd)
- X " " (prin1-to-string fcmd) ")\n")))
- X (insert " (define-key calc-mode-map "
- X (prin1-to-string (concat "z" (char-to-string key)))
- X " '"
- X (prin1-to-string cmd)
- X "))\n"))
- X (insert " (and (boundp 'calc-defs) calc-defs)))\n")
- X (save-buffer)))
- X)
- X
- X(defun calc-stack-command-p (cmd)
- X (if (and cmd (symbolp cmd))
- X (and (fboundp cmd)
- X (calc-stack-command-p (symbol-function cmd)))
- X (and (consp cmd)
- X (eq (car cmd) 'lambda)
- X (setq cmd (or (assq 'calc-wrapper cmd)
- X (assq 'calc-slow-wrapper cmd)))
- X (setq cmd (assq 'calc-enter-result cmd))
- X (memq (car (nth 3 cmd)) '(cons list))
- X (eq (car (nth 1 (nth 3 cmd))) 'quote)
- X (nth 1 (nth 1 (nth 3 cmd)))))
- X)
- X
- X(defun calc-permanent-variable ()
- X "Save a variable's value in your .emacs file."
- X (interactive)
- X (calc-wrapper
- X (let ((var (let ((minibuffer-completion-table obarray)
- X (minibuffer-completion-predicate 'boundp)
- X (minibuffer-completion-confirm t)
- X (oper "r"))
- X (read-from-minibuffer
- X "Save variable: " "var-" calc-store-var-map nil)))
- X pos)
- X (if (equal var "")
- X ()
- X (or (and (boundp (intern var)) (intern var))
- X (error "No such variable"))
- X (set-buffer (find-file-noselect (substitute-in-file-name
- X calc-settings-file)))
- X (goto-char (point-min))
- X (if (search-forward (concat "(setq " var " '") nil t)
- X (progn
- X (setq pos (point-marker))
- X (forward-line -1)
- X (if (looking-at ";;; Variable .* stored by Calc on ")
- X (progn
- X (delete-region (match-end 0) (progn (end-of-line) (point)))
- X (insert (current-time-string))))
- X (goto-char (- pos 8 (length var)))
- X (forward-sexp 1)
- X (backward-char 1)
- X (delete-region pos (point)))
- X (goto-char (point-max))
- X (insert "\n;;; Variable \""
- X var
- X "\" stored by Calc on "
- X (current-time-string)
- X "\n(setq "
- X var
- X " ')\n")
- X (backward-char 2))
- X (insert (prin1-to-string (symbol-value (intern var))))
- X (forward-line 1)
- X (save-buffer))))
- X)
- X
- X
- X
- X(defun calc-call-last-kbd-macro (arg)
- X "Execute the most recent keyboard macro."
- X (interactive "P")
- X (and defining-kbd-macro
- X (error "Can't execute anonymous macro while defining one"))
- X (or last-kbd-macro
- X (error "No kbd macro has been defined"))
- X (calc-execute-kbd-macro last-kbd-macro arg)
- X)
- X
- X(defun calc-execute-kbd-macro (mac arg)
- X (if (< (prefix-numeric-value arg) 0)
- X (execute-kbd-macro mac (- (prefix-numeric-value arg)))
- X (if calc-executing-macro
- X (execute-kbd-macro mac arg)
- X (calc-slow-wrapper
- X (let ((old-stack-whole (copy-sequence calc-stack))
- X (old-stack-top calc-stack-top)
- X (old-buffer-size (buffer-size))
- X (old-refresh-count calc-refresh-count))
- X (unwind-protect
- X (let ((calc-executing-macro mac))
- X (execute-kbd-macro mac arg))
- X (calc-select-buffer)
- X (let ((new-stack (reverse calc-stack))
- X (old-stack (reverse old-stack-whole)))
- X (while (and new-stack old-stack
- X (equal (car new-stack) (car old-stack)))
- X (setq new-stack (cdr new-stack)
- X old-stack (cdr old-stack)))
- X (calc-record-list (mapcar 'car new-stack) "kmac")
- X (calc-record-undo (list 'set 'saved-stack-top old-stack-top))
- X (and old-stack
- X (calc-record-undo (list 'pop 1 (mapcar 'car old-stack))))
- X (let ((calc-stack old-stack-whole)
- X (calc-stack-top 0))
- X (calc-cursor-stack-index (length old-stack)))
- X (if (and (= old-buffer-size (buffer-size))
- X (= old-refresh-count calc-refresh-count))
- X (let ((buffer-read-only nil))
- X (delete-region (point) (point-max))
- X (while new-stack
- X (calc-record-undo (list 'push 1))
- X (let ((fmt (math-format-stack-value
- X (car (car new-stack)))))
- X (setcar (cdr (car new-stack)) (calc-count-lines fmt))
- X (insert fmt "\n"))
- X (setq new-stack (cdr new-stack)))
- X (calc-renumber-stack))
- X (calc-refresh))
- X (calc-record-undo (list 'set 'saved-stack-top 0))))))))
- X)
- X
- X
- X(defun calc-kbd-if ()
- X "An \"if\" statement in a Calc keyboard macro.
- XUsage: cond Z[ then-part Z: cond Z| else-if-part ... Z: else-part Z]"
- X (interactive)
- X (calc-wrapper
- X (let ((cond (calc-top-n 1)))
- X (calc-pop-stack 1)
- X (if (math-is-true cond)
- X (if defining-kbd-macro
- X (message "If true..."))
- X (if defining-kbd-macro
- X (message "Condition is false; skipping to Z: or Z] ..."))
- X (calc-kbd-skip-to-else-if t))))
- X)
- X
- X(defun calc-kbd-else-if ()
- X (interactive)
- X (calc-kbd-if)
- X)
- X
- X(defun calc-kbd-skip-to-else-if (else-okay)
- X (let ((count 0)
- X ch)
- X (while (>= count 0)
- X (setq ch (read-char))
- X (if (= ch -1)
- X (error "Unterminated Z[ in keyboard macro"))
- X (if (= ch ?Z)
- X (progn
- X (setq ch (read-char))
- X (cond ((= ch ?\[)
- X (setq count (1+ count)))
- X ((= ch ?\])
- X (setq count (1- count)))
- X ((= ch ?\:)
- X (and (= count 0)
- X else-okay
- X (setq count -1)))
- X ((eq ch 7)
- X (keyboard-quit))))))
- X (and defining-kbd-macro
- X (if (= ch ?\:)
- X (message "Else...")
- X (message "End-if..."))))
- X)
- X
- X(defun calc-kbd-end-if ()
- X (interactive)
- X (if defining-kbd-macro
- X (message "End-if..."))
- X)
- X
- X(defun calc-kbd-else ()
- X (interactive)
- X (if defining-kbd-macro
- X (message "Else; skipping to Z] ..."))
- X (calc-kbd-skip-to-else-if nil)
- X)
- X
- X
- X(defun calc-kbd-repeat ()
- X "A counted loop in a Calc keyboard macro.
- XUsage: count Z< body Z>
- X
- XAny number of break-commands may be embedded in the body:
- X cond Z/ stops the loop prematurely if cond is true."
- X (interactive)
- X (let (count)
- X (calc-wrapper
- X (setq count (math-trunc (calc-top-n 1)))
- X (or (Math-integerp count)
- X (error "Count must be an integer"))
- X (if (Math-integer-negp count)
- X (setq count 0))
- X (or (integerp count)
- X (setq count 1000000))
- X (calc-pop-stack 1))
- X (calc-kbd-loop count))
- X)
- X
- X(defun calc-kbd-for (dir)
- X "A counted loop in a Calc keyboard macro.
- XUsage: initial final Z( body step Z)
- X
- XDuring the loop, an internal counter is incremented from INITIAL to FINAL
- Xin steps of STEP. The Z( command pops INITIAL and FINAL, and pushes the
- Xcurrent counter value each time through the loop. The Z) command pops
- XSTEP. If INITIAL < FINAL, the loop terminates as soon as the counter
- Xexceeds FINAL. If INITIAL > FINAL, the loop terminates as soon as the
- Xcounter becomes less than FINAL. If INITIAL = FINAL, the loop executes
- Xonce. If INITIAL and FINAL cannot be compared (say because at least one
- Xis a symbolic formula), the loop continues until it is halted with Z/.
- XNo matter what the relationship between INITIAL and FINAL, the body
- Xalways executes at least once.
- X
- XA numeric prefix argument specifies a forced direction: If 1, the loop
- Xterminates when the counter exceeds FINAL, and will execute zero times
- Xif INITIAL > FINAL. Likewise, -1 forces a downward-counting loop.
- X
- XAny number of break-commands may be embedded in the body:
- X cond Z/ stops the loop prematurely if cond is true."
- X (interactive "P")
- X (let (init final)
- X (calc-wrapper
- X (setq init (calc-top-n 2)
- X final (calc-top-n 1))
- X (or (and (math-anglep init) (math-anglep final))
- X (error "Initial and final values must be real numbers"))
- X (calc-pop-stack 2))
- X (calc-kbd-loop nil init final (and dir (prefix-numeric-value dir))))
- X)
- X
- X(defun calc-kbd-loop (rpt-count &optional initial final dir)
- X "A conditional loop in a Calc keyboard macro.
- XUsage: Z{ body Z}
- X
- XAt least one break-command is normally present in the body:
- X cond Z/ stops the loop if cond is true.
- X
- XWith a numeric prefix argument, loops at most that many times."
- X (interactive "P")
- X (setq rpt-count (if rpt-count (prefix-numeric-value rpt-count) 1000000))
- X (let* ((count 0)
- X (parts nil)
- X (body "")
- X (open last-command-char)
- X (counter initial)
- X ch)
- X (or executing-macro
- X (message "Reading loop body..."))
- X (while (>= count 0)
- X (setq ch (read-char))
- X (if (= ch -1)
- X (error "Unterminated Z%c in keyboard macro" open))
- X (if (= ch ?Z)
- X (progn
- X (setq ch (read-char)
- X body (concat body "Z" (char-to-string ch)))
- X (cond ((memq ch '(?\< ?\( ?\{))
- X (setq count (1+ count)))
- X ((memq ch '(?\> ?\) ?\}))
- X (setq count (1- count)))
- X ((and (= ch ?/)
- X (= count 0))
- X (setq parts (nconc parts (list (substring body 0 -2)))
- X body ""))
- X ((eq ch 7)
- X (keyboard-quit))))
- X (setq body (concat body (char-to-string ch)))))
- X (if (/= ch (cdr (assq open '( (?\< . ?\>) (?\( . ?\)) (?\{ . ?\}) ))))
- X (error "Mismatched Z%c and Z%c in keyboard macro" open ch))
- X (or executing-macro
- X (message "Looping..."))
- X (setq body (substring body 0 -2))
- X (and (not executing-macro)
- X (= rpt-count 1000000)
- X (null parts)
- X (null counter)
- X (progn
- X (message "Warning: Infinite loop! Not executing.")
- X (setq rpt-count 0)))
- X (or (not initial) dir
- X (setq dir (math-compare final initial)))
- X (calc-wrapper
- X (while (> rpt-count 0)
- X (let ((part parts))
- X (if counter
- X (if (cond ((eq dir 0) (math-equal final counter))
- X ((eq dir 1) (math-lessp final counter))
- X ((eq dir -1) (math-lessp counter final)))
- X (setq rpt-count 0)
- X (calc-push counter)))
- X (while (and part (> rpt-count 0))
- X (execute-kbd-macro (car part))
- X (if (math-is-true (calc-top-n 1))
- X (setq rpt-count 0)
- X (setq part (cdr part)))
- X (calc-pop-stack 1))
- X (if (> rpt-count 0)
- X (progn
- X (execute-kbd-macro body)
- X (if counter
- X (let ((step (calc-top-n 1)))
- X (calc-pop-stack 1)
- X (setq counter (calcFunc-add counter step)))
- X (setq rpt-count (1- rpt-count))))))))
- X (or executing-macro
- X (message "Looping...done")))
- X)
- X
- X(defun calc-kbd-end-repeat ()
- X (interactive)
- X (error "Unbalanced Z> in keyboard macro")
- X)
- X
- X(defun calc-kbd-end-for ()
- X (interactive)
- X (error "Unbalanced Z) in keyboard macro")
- X)
- X
- X(defun calc-kbd-end-loop ()
- X (interactive)
- X (error "Unbalanced Z} in keyboard macro")
- X)
- X
- X(defun calc-kbd-break ()
- X "Break out of a keyboard macro, or out of a Z< Z> or Z{ Z} loop in a macro.
- XUsage: cond Z/ breaks only if cond is true. Use \"1 Z/\" to break always."
- X (interactive)
- X (calc-wrapper
- X (let ((cond (calc-top-n 1)))
- X (calc-pop-stack 1)
- X (if (math-is-true cond)
- X (error "Keyboard macro aborted."))))
- X)
- X
- X
- X(defun calc-kbd-push ()
- X "Save modes and quick variables around a section of a keyboard macro.
- X
- XSaved: var-0 thru var-9, precision, word size, angular mode,
- Xsimplification mode, vector mapping direction, Alg, Sym, Frac, Polar modes.
- X
- XValues are restored on exit, even if the macro halts with an error."
- X (interactive)
- X (calc-wrapper
- X (let* ((var-0 (and (boundp 'var-0) var-0))
- X (var-1 (and (boundp 'var-1) var-1))
- X (var-2 (and (boundp 'var-2) var-2))
- X (var-3 (and (boundp 'var-3) var-3))
- X (var-4 (and (boundp 'var-4) var-4))
- X (var-5 (and (boundp 'var-5) var-5))
- X (var-6 (and (boundp 'var-6) var-6))
- X (var-7 (and (boundp 'var-7) var-7))
- X (var-8 (and (boundp 'var-8) var-8))
- X (var-9 (and (boundp 'var-9) var-9))
- X (calc-internal-prec calc-internal-prec)
- X (calc-word-size calc-word-size)
- X (calc-angle-mode calc-angle-mode)
- X (calc-simplify-mode calc-simplify-mode)
- X (calc-mapping-dir calc-mapping-dir)
- X (calc-algebraic-mode calc-algebraic-mode)
- X (calc-symbolic-mode calc-symbolic-mode)
- X (calc-prefer-frac calc-prefer-frac)
- X (calc-complex-mode calc-complex-mode)
- X (count 0)
- X (body "")
- X ch)
- X (if (or executing-macro defining-kbd-macro)
- X (progn
- X (if defining-kbd-macro
- X (message "Reading body..."))
- X (while (>= count 0)
- X (setq ch (read-char))
- X (if (= ch -1)
- X (error "Unterminated Z` in keyboard macro"))
- X (if (= ch ?Z)
- X (progn
- X (setq ch (read-char)
- X body (concat body "Z" (char-to-string ch)))
- X (cond ((eq ch ?\`)
- X (setq count (1+ count)))
- X ((eq ch ?\')
- X (setq count (1- count)))
- X ((eq ch 7)
- X (keyboard-quit))))
- X (setq body (concat body (char-to-string ch)))))
- X (if defining-kbd-macro
- X (message "Reading body...done"))
- X (let ((calc-kbd-push-level 0))
- X (execute-kbd-macro (substring body 0 -2))))
- X (let ((calc-kbd-push-level (1+ calc-kbd-push-level)))
- X (message "Saving modes; type Z' to restore")
- X (recursive-edit)))))
- X)
- X(setq calc-kbd-push-level 0)
- X
- X(defun calc-kbd-pop ()
- X (interactive)
- X (if (> calc-kbd-push-level 0)
- X (progn
- X (message "Mode settings restored")
- X (exit-recursive-edit))
- X (error "Unbalanced Z' in keyboard macro"))
- X)
- X
- X
- X(defun calc-kbd-report (msg)
- X "Display the number on the top of the stack in the echo area.
- XThis will normally be used to report progress in a keyboard macro."
- X (interactive "sMessage: ")
- X (calc-wrapper
- X (let ((executing-macro nil)
- X (defining-kbd-macro nil))
- X (math-working msg (calc-top-n 1))))
- X)
- X
- X(defun calc-kbd-query (msg)
- X "Pause during keyboard macro execution to do an algebraic entry."
- X (interactive "sPrompt: ")
- X (calc-wrapper
- X (let ((executing-macro nil)
- X (defining-kbd-macro nil))
- X (calc-alg-entry nil (and (not (equal msg "")) msg))))
- X)
- X
- X
- X
- X
- X
- X
- X;;;; Caches.
- X
- X(defmacro math-defcache (name init form)
- X (let ((cache-prec (intern (concat (symbol-name name) "-cache-prec")))
- X (cache-val (intern (concat (symbol-name name) "-cache")))
- X (last-prec (intern (concat (symbol-name name) "-last-prec")))
- X (last-val (intern (concat (symbol-name name) "-last"))))
- X (list 'progn
- X (list 'setq cache-prec (if init (math-numdigs (nth 1 init)) -100))
- X (list 'setq cache-val (list 'quote init))
- X (list 'setq last-prec -100)
- X (list 'setq last-val nil)
- X (list 'setq 'math-cache-list
- X (list 'cons
- X (list 'quote cache-prec)
- X (list 'cons
- X (list 'quote last-prec)
- X 'math-cache-list)))
- X (list 'defun
- X name ()
- X (list 'or
- X (list '= last-prec 'calc-internal-prec)
- X (list 'setq
- X last-val
- X (list 'math-normalize
- X (list 'progn
- X (list 'or
- X (list '>= cache-prec
- X 'calc-internal-prec)
- X (list 'setq
- X cache-val
- X (list 'let
- X '((calc-internal-prec
- X (+ calc-internal-prec
- X 4)))
- X form)
- X cache-prec
- X '(+ calc-internal-prec 2)))
- X cache-val))
- X last-prec 'calc-internal-prec))
- X last-val)))
- X)
- X(put 'math-defcache 'lisp-indent-hook 2)
- X
- X;;; Betcha didn't know that pi = 16 atan(1/5) - 4 atan(1/239). [F] [Public]
- X(math-defcache math-pi (float (bigpos 463 238 793 589 653 592 141 3) -21)
- X (math-add-float (math-mul-float '(float 16 0)
- X (math-arctan-raw '(float 2 -1)))
- X (math-mul-float '(float -4 0)
- X (math-arctan-raw
- X (math-float '(frac 1 239))))))
- X
- X(math-defcache math-two-pi nil
- X (math-mul-float (math-pi) '(float 2 0)))
- X
- X(math-defcache math-pi-over-2 nil
- X (math-mul-float (math-pi) '(float 5 -1)))
- X
- X(math-defcache math-pi-over-4 nil
- X (math-mul-float (math-pi) '(float 25 -2)))
- X
- X(math-defcache math-pi-over-180 nil
- X (math-div-float (math-pi) '(float 18 1)))
- X
- X(math-defcache math-sqrt-e (float (bigpos 849 146 128 700 270 721 648 1) -21)
- X (math-add-float '(float 1 0) (math-exp-minus-1-raw '(float 5 -1))))
- X
- X(math-defcache math-e nil
- X (math-sqr (math-sqrt-e)))
- X
- X
- X(defun math-half-circle (symb)
- X (if (eq calc-angle-mode 'rad)
- X (if symb
- X '(var pi var-pi)
- X (math-pi))
- X 180)
- X)
- X
- X(defun math-full-circle (symb)
- X (math-mul 2 (math-half-circle symb))
- X)
- X
- X(defun math-quarter-circle (symb)
- X (math-div (math-half-circle symb) 2)
- X)
- X
- X
- X
- X
- X;;;; Miscellaneous math routines.
- X
- X;;; True if A is an odd integer. [P R R] [Public]
- X(defun math-oddp (a)
- X (if (consp a)
- X (and (memq (car a) '(bigpos bigneg))
- X (= (% (nth 1 a) 2) 1))
- X (/= (% a 2) 0))
- X)
- X
- X;;; True if A is numerically an integer. [P x] [Public]
- X(defun math-num-integerp (a)
- X (or (Math-integerp a)
- X (Math-messy-integerp a))
- X)
- X(defmacro Math-num-integerp (a)
- X (` (or (not (consp (, a)))
- X (memq (car (, a)) '(bigpos bigneg))
- X (and (eq (car (, a)) 'float)
- X (>= (nth 2 (, a)) 0))))
- X)
- X
- X;;; True if A is (numerically) a non-negative integer. [P N] [Public]
- X(defun math-num-natnump (a)
- X (or (natnump a)
- X (eq (car-safe a) 'bigpos)
- X (and (eq (car-safe a) 'float)
- X (Math-natnump (nth 1 a))
- X (>= (nth 2 a) 0)))
- X)
- X
- X;;; True if A is an integer or will evaluate to an integer. [P x] [Public]
- X(defun math-provably-integerp (a)
- X (or (Math-integerp a)
- X (memq (car-safe a) '(calcFunc-trunc
- X calcFunc-round
- X calcFunc-floor
- X calcFunc-ceil)))
- X)
- X
- X;;; True if A is a real or will evaluate to a real. [P x] [Public]
- X(defun math-provably-realp (a)
- X (or (Math-realp a)
- X (math-provably-integer a)
- X (memq (car-safe a) '(abs arg)))
- X)
- X
- X;;; True if A is a non-real, complex number. [P x] [Public]
- X(defun math-complexp (a)
- X (memq (car-safe a) '(cplx polar))
- X)
- X
- X;;; True if A is a non-real, rectangular complex number. [P x] [Public]
- X(defun math-rect-complexp (a)
- X (eq (car-safe a) 'cplx)
- X)
- X
- X;;; True if A is a non-real, polar complex number. [P x] [Public]
- X(defun math-polar-complexp (a)
- X (eq (car-safe a) 'polar)
- X)
- X
- X;;; True if A is a matrix. [P x] [Public]
- X(defun math-matrixp (a)
- X (and (Math-vectorp a)
- X (Math-vectorp (nth 1 a))
- X (cdr (nth 1 a))
- X (math-matrixp-step (cdr (cdr a)) (length (nth 1 a))))
- X)
- X
- X(defun math-matrixp-step (a len) ; [P L]
- X (or (null a)
- X (and (Math-vectorp (car a))
- X (= (length (car a)) len)
- X (math-matrixp-step (cdr a) len)))
- X)
- X
- X;;; True if A is a square matrix. [P V] [Public]
- X(defun math-square-matrixp (a)
- X (let ((dims (math-mat-dimens a)))
- X (and (cdr dims)
- X (= (car dims) (nth 1 dims))))
- X)
- X
- X;;; True if A is any real scalar data object. [P x]
- X(defun math-real-objectp (a) ; [Public]
- X (or (integerp a)
- X (memq (car-safe a) '(bigpos bigneg frac float hms sdev intv mod)))
- X)
- X
- X;;; True if A is an object not composed of sub-formulas . [P x] [Public]
- X(defun math-primp (a)
- X (or (integerp a)
- X (memq (car-safe a) '(bigpos bigneg frac float cplx polar
- X hms mod var)))
- X)
- X(defmacro Math-primp (a)
- X (` (or (not (consp (, a)))
- X (memq (car (, a)) '(bigpos bigneg frac float cplx polar
- X hms mod var))))
- X)
- X
- X;;; True if A is a constant or vector of constants. [P x] [Public]
- X(defun math-constp (a)
- X (or (math-scalarp a)
- X (and (memq (car-safe a) '(sdev intv vec))
- X (progn
- X (while (and (setq a (cdr a))
- X (math-constp (car a))))
- X (null a))))
- X)
- X
- X(defmacro Math-lessp (a b)
- X (` (= (math-compare (, a) (, b)) -1))
- X)
- X
- X
- X;;; Verify that A is an integer and return A in integer form. [I N; - x]
- X(defun math-check-integer (a) ; [Public]
- X (cond ((integerp a) a) ; for speed
- X ((math-integerp a) a)
- X ((math-messy-integerp a)
- X (math-trunc a))
- X (t (math-reject-arg a 'integerp)))
- X)
- X
- X;;; Verify that A is a small integer and return A in integer form. [S N; - x]
- X(defun math-check-fixnum (a) ; [Public]
- X (cond ((integerp a) a) ; for speed
- X ((Math-num-integerp a)
- X (let ((a (math-trunc a)))
- X (if (integerp a)
- X a
- X (if (or (Math-lessp (lsh -1 -1) a)
- X (Math-lessp a (- (lsh -1 -1))))
- X (math-reject-arg a 'fixnump)
- X (math-fixnum a)))))
- X (t (math-reject-arg a 'fixnump)))
- X)
- X
- X;;; Verify that A is an integer >= 0 and return A in integer form. [I N; - x]
- X(defun math-check-natnum (a) ; [Public]
- X (cond ((natnump a) a)
- X ((and (not (math-negp a))
- X (Math-num-integerp a))
- X (math-trunc a))
- X (t (math-reject-arg a 'natnump)))
- X)
- X
- X;;; Verify that A is in floating-point form, or force it to be a float. [F N]
- X(defun math-check-float (a) ; [Public]
- X (cond ((eq (car-safe a) 'float) a)
- X ((Math-vectorp a) (math-map-vec 'math-check-float a))
- X ((Math-objectp a) (math-float a))
- X (t a))
- X)
- X
- X;;; Verify that A is a constant.
- X(defun math-check-const (a)
- X (if (math-constp a)
- X a
- X (math-reject-arg a 'constp))
- X)
- X
- X
- X;;; Coerce integer A to be a small integer. [S I]
- X(defun math-fixnum (a)
- X (if (consp a)
- X (if (cdr a)
- X (if (eq (car a) 'bigneg)
- X (- (math-fixnum-big (cdr a)))
- X (math-fixnum-big (cdr a)))
- X 0)
- X a)
- X)
- X
- X(defun math-fixnum-big (a)
- X (if (cdr a)
- X (+ (car a) (* (math-fixnum-big (cdr a)) 1000))
- X (car a))
- X)
- X
- X
- X(defun math-bignum-test (a) ; [B N; B s; b b]
- X (if (consp a)
- X a
- X (math-bignum a))
- X)
- X(defmacro Math-bignum-test (a) ; [B N; B s; b b]
- X (` (if (consp (, a))
- X (, a)
- X (math-bignum (, a))))
- X)
- X
- X
- X;;; Return 0 for zero, -1 for negative, 1 for positive. [S n] [Public]
- X(defun math-sign (a)
- X (cond ((math-posp a) 1)
- X ((math-negp a) -1)
- X ((math-zerop a) 0)
- X (t (calc-record-why 'realp a)
- X (list 'calcFunc-sign a)))
- X)
- X(fset 'calcFunc-sign (symbol-function 'math-sign))
- X
- X;;; Return 0 if A is numerically equal to B, <0 if less, >0 if more.
- X;;; Arguments must be normalized! [S N N]
- X(defun math-compare (a b)
- X (cond ((equal a b) 0)
- X ((and (integerp a) (Math-integerp b))
- X (if (consp b)
- X (if (eq (car b) 'bigpos) -1 1)
- X (if (< a b) -1 1)))
- X ((and (eq (car-safe a) 'bigpos) (Math-integerp b))
- X (if (eq (car-safe b) 'bigpos)
- X (math-compare-bignum (cdr a) (cdr b))
- X 1))
- X ((and (eq (car-safe a) 'bigneg) (Math-integerp b))
- X (if (eq (car-safe b) 'bigneg)
- X (math-compare-bignum (cdr b) (cdr a))
- X -1))
- X ((eq (car-safe a) 'frac)
- X (if (eq (car-safe b) 'frac)
- X (math-compare (math-mul (nth 1 a) (nth 2 b))
- X (math-mul (nth 1 b) (nth 2 a)))
- X (math-compare (nth 1 a) (math-mul b (nth 2 a)))))
- X ((eq (car-safe b) 'frac)
- X (math-compare (math-mul a (nth 2 b)) (nth 1 b)))
- X ((and (eq (car-safe a) 'float) (eq (car-safe b) 'float))
- X (if (math-lessp-float a b) -1 1))
- X ((and (Math-anglep a) (Math-anglep b))
- X (math-sign (math-add a (math-neg b))))
- X ((eq (car-safe a) 'var)
- X 2)
- X (t
- X (if (and (consp a) (consp b)
- X (eq (car a) (car b))
- X (math-compare-lists (cdr a) (cdr b)))
- X 0
- X 2)))
- X)
- X
- X;;; Compare two bignum digit lists, return -1 for A<B, 0 for A=B, 1 for A>B.
- X(defun math-compare-bignum (a b) ; [S l l]
- X (let ((res 0))
- X (while (and a b)
- X (if (< (car a) (car b))
- X (setq res -1)
- X (if (> (car a) (car b))
- X (setq res 1)))
- X (setq a (cdr a)
- X b (cdr b)))
- X (if a
- X (progn
- X (while (eq (car a) 0) (setq a (cdr a)))
- X (if a 1 res))
- X (while (eq (car b) 0) (setq b (cdr b)))
- X (if b -1 res)))
- X)
- X
- X(defun math-compare-lists (a b)
- X (cond ((null a) (null b))
- X ((null b) nil)
- X (t (and (math-equal (car a) (car b))
- X (math-compare-lists (cdr a) (cdr b)))))
- X)
- X
- X(defun math-lessp-float (a b) ; [P F F]
- X (let ((ediff (- (nth 2 a) (nth 2 b))))
- X (if (>= ediff 0)
- X (if (>= ediff (+ calc-internal-prec calc-internal-prec))
- X (Math-integer-negp (nth 1 a))
- X (Math-lessp (math-scale-int (nth 1 a) ediff)
- X (nth 1 b)))
- X (if (>= (setq ediff (- ediff))
- X (+ calc-internal-prec calc-internal-prec))
- X (Math-integer-posp (nth 1 b))
- X (Math-lessp (nth 1 a)
- X (math-scale-int (nth 1 b) ediff)))))
- X)
- X
- X;;; True if A is numerically equal to B. [P N N] [Public]
- X(defun math-equal (a b)
- X (= (math-compare a b) 0)
- X)
- X
- X;;; True if A is numerically less than B. [P R R] [Public]
- X(defun math-lessp (a b)
- X (= (math-compare a b) -1)
- X)
- X
- X;;; True if A is numerically equal to the integer B. [P N S] [Public]
- X;;; B must not be a multiple of 10.
- X(defun math-equal-int (a b)
- X (or (eq a b)
- X (and (eq (car-safe a) 'float)
- X (eq (nth 1 a) b)
- X (= (nth 2 a) 0)))
- X)
- X(defmacro Math-equal-int (a b)
- X (` (or (eq (, a) (, b))
- X (and (consp (, a))
- X (eq (car (, a)) 'float)
- X (eq (nth 1 (, a)) (, b))
- X (= (nth 2 (, a)) 0))))
- X)
- X
- X
- X;;; Convert a variable name (as a formula) into a like-looking function name.
- X(defun math-var-to-calcFunc (f)
- X (if (eq (car-safe f) 'var)
- X (if (fboundp (nth 2 f))
- X (nth 2 f)
- X (intern (concat "calcFunc-" (symbol-name (nth 1 f)))))
- X (if (memq (car-safe f) '(lambda calcFunc-lambda))
- X f
- X (math-reject-arg f "Expected a function name")))
- X)
- X
- X;;; Convert a function name into a like-looking variable name formula.
- X(defun math-calcFunc-to-var (f)
- X (if (symbolp f)
- X (let ((base (if (string-match "\\`calcFunc-\\(.+\\)\\'" (symbol-name f))
- X (math-match-substring (symbol-name f) 1)
- X (symbol-name f))))
- X (list 'var
- X (intern base)
- X (intern (concat "var-" base))))
- X f)
- X)
- X
- X;;; Expand a function call using "lambda" notation.
- X(defun math-build-call (f args)
- X (if (eq (car-safe f) 'calcFunc-lambda)
- X (if (= (length args) (- (length f) 2))
- X (let ((argnames (cdr f))
- X (argvals args)
- X (res (nth (1- (length f)) f)))
- X (while argvals
- X (setq res (math-expr-subst res (car argnames) (car argvals))
- X argnames (cdr argnames)
- X argvals (cdr argvals)))
- X res)
- X (cons 'calcFunc-call (cons (math-calcFunc-to-var f) args)))
- X (cons f args))
- X)
- X
- X(defun calcFunc-call (f &rest args)
- X (setq args (math-build-call (math-var-to-calcFunc f) args))
- X (if (eq (car-safe args) 'calcFunc-call)
- X args
- X (math-normalize args))
- X)
- X
- X(defun calcFunc-apply (f args)
- X (or (Math-vectorp args)
- X (math-reject-arg args 'vectorp))
- X (apply 'calcFunc-call (cons f (cdr args)))
- X)
- X
- X
- X
- X;;;; Vectors.
- X
- X;;; Return the dimensions of a matrix as a list. [l x] [Public]
- X(defun math-mat-dimens (m)
- X (if (math-vectorp m)
- X (if (math-matrixp m)
- X (cons (1- (length m))
- X (math-mat-dimens (nth 1 m)))
- X (list (1- (length m))))
- X nil)
- X)
- X
- X
- X;;; Apply a function elementwise to vector A. [V X V; N X N] [Public]
- X(defun math-map-vec (f a)
- X (if (math-vectorp a)
- X (cons 'vec (mapcar f (cdr a)))
- X (funcall f a))
- X)
- X
- X(defun math-dimension-error ()
- X (calc-record-why "Dimension error")
- X (signal 'wrong-type-argument nil)
- X)
- X
- X
- X;;; Build a vector out of a list of objects. [Public]
- X(defun math-build-vector (&rest objs)
- X (cons 'vec objs)
- X)
- X(fset 'calcFunc-vec (symbol-function 'math-build-vector))
- X
- X
- X;;; Build a constant vector or matrix. [Public]
- X(defun math-make-vec (obj &rest dims)
- X (math-make-vec-dimen obj dims)
- X)
- X(fset 'calcFunc-cvec (symbol-function 'math-make-vec))
- X
- X(defun math-make-vec-dimen (obj dims)
- X (if dims
- X (if (natnump (car dims))
- X (if (or (cdr dims)
- X (not (math-numberp obj)))
- X (cons 'vec (copy-sequence
- X (make-list (car dims)
- X (math-make-vec-dimen obj (cdr dims)))))
- X (cons 'vec (make-list (car dims) obj)))
- X (math-reject-arg (car dims) 'natnump))
- X obj)
- X)
- X
- X
- X;;; Coerce row vector A to be a matrix. [V V]
- X(defun math-row-matrix (a)
- X (if (and (Math-vectorp a)
- X (not (math-matrixp a)))
- X (list 'vec a)
- X a)
- X)
- X
- X;;; Coerce column vector A to be a matrix. [V V]
- X(defun math-col-matrix (a)
- X (if (and (Math-vectorp a)
- X (not (math-matrixp a)))
- X (cons 'vec (mapcar (function (lambda (x) (list 'vec x))) (cdr a)))
- X a)
- X)
- X
- X
- X(defun calc-binary-op-fancy (name func arg ident unary)
- X (let ((n (prefix-numeric-value arg)))
- X (cond ((> n 1)
- X (calc-enter-result n
- X name
- X (list 'calcFunc-reduce
- X (math-calcFunc-to-var func)
- X (cons 'vec (calc-top-list-n n)))))
- X ((= n 1)
- X (if unary
- X (calc-enter-result 1 name (list unary (calc-top-n 1)))))
- X ((= n 0)
- X (if ident
- X (calc-enter-result 0 name ident)
- X (error "Argument must be nonzero")))
- X (t
- X (let ((rhs (calc-top-n 1)))
- X (calc-enter-result (- 1 n)
- X name
- X (mapcar (function
- X (lambda (x)
- X (list func x rhs)))
- X (calc-top-list-n (- n) 2)))))))
- X)
- X
- X(defun calc-unary-op-fancy (name func arg)
- X (let ((n (prefix-numeric-value arg)))
- X (cond ((> n 0)
- X (calc-enter-result n
- X name
- X (mapcar (function
- X (lambda (x)
- X (list func x)))
- X (calc-top-list-n n))))
- X ((= n 0))
- X (t
- X (error "Argument must be positive"))))
- X)
- X
- X
- X;;; Apply a function elementwise to vectors A and B. [O X O O] [Public]
- X(defun math-map-vec-2 (f a b)
- X (if (math-vectorp a)
- X (if (math-vectorp b)
- X (cons 'vec (math-map-vec-2-step f (cdr a) (cdr b)))
- X (cons 'vec (math-map-vec-2-left f (cdr a) b)))
- X (if (math-vectorp b)
- X (cons 'vec (math-map-vec-2-right f a (cdr b)))
- X (funcall f a b)))
- X)
- X
- X(defun math-map-vec-2-step (f a b) ; [L X L L]
- X (cond
- X ((null a) (if b (math-dimension-error)))
- X ((null b) (math-dimension-error))
- X (t (cons (funcall f (car a) (car b))
- X (math-map-vec-2-step f (cdr a) (cdr b)))))
- X)
- X
- X(defun math-map-vec-2-left (f a b) ; [L X L N]
- X (and a
- X (cons (funcall f (car a) b)
- X (math-map-vec-2-left f (cdr a) b)))
- X)
- X
- X(defun math-map-vec-2-right (f a b) ; [L X N L]
- X (and b
- X (cons (funcall f a (car b))
- X (math-map-vec-2-right f a (cdr b))))
- X)
- X
- X
- X;;; Map a function over a vector symbolically. [Public]
- X(defun math-symb-map (f mode args)
- X (let* ((func (math-var-to-calcFunc f))
- X (nargs (length args))
- X (ptrs (vconcat args))
- X (vflags (make-vector nargs nil))
- X (vec nil)
- X (i -1)
- X len cols obj expr)
- X (if (eq mode 'rows)
- X ()
- X (while (and (< (setq i (1+ i)) nargs)
- X (not (math-matrixp (aref ptrs i)))))
- X (if (< i nargs)
- X (if (eq mode 'elems)
- X (setq func (list 'lambda '(&rest x)
- X (list 'math-symb-map
- X (list 'quote f) '(quote elems) 'x))
- X mode 'rows)
- X (while (< i nargs)
- X (if (math-matrixp (aref ptrs i))
- X (aset ptrs i (math-transpose (aref ptrs i))))
- X (setq i (1+ i))))
- X (setq mode 'elems))
- X (setq i -1))
- X (while (< (setq i (1+ i)) nargs)
- X (setq obj (aref ptrs i))
- X (if (and (eq (car-safe obj) 'vec)
- X (or (eq mode 'elems)
- X (math-matrixp obj)))
- X (progn
- X (aset vflags i t)
- X (if len
- X (or (= (length obj) len)
- X (math-dimension-error))
- X (setq len (length obj))))))
- X (or len
- X (if (= nargs 1)
- X (math-reject-arg (aref ptrs 0) 'vectorp)
- X (math-reject-arg "At least one argument must be a vector")))
- X (while (> (setq len (1- len)) 0)
- X (setq expr nil
- X i -1)
- X (while (< (setq i (1+ i)) nargs)
- X (if (aref vflags i)
- X (progn
- X (aset ptrs i (cdr (aref ptrs i)))
- X (setq expr (nconc expr (list (car (aref ptrs i))))))
- X (setq expr (nconc expr (list (aref ptrs i))))))
- X (setq vec (cons (math-build-call func expr) vec)))
- X (if (eq mode 'cols)
- X (math-transpose (math-normalize (cons 'vec (nreverse vec))))
- X (math-normalize (cons 'vec (nreverse vec)))))
- X)
- X
- X(defun calcFunc-map (func &rest args)
- X (math-symb-map func 'elems args)
- X)
- X
- X(defun calcFunc-mapr (func &rest args)
- X (math-symb-map func 'rows args)
- X)
- X
- X(defun calcFunc-mapc (func &rest args)
- X (math-symb-map func 'cols args)
- X)
- X
- X(defun calcFunc-mapa (func arg)
- X (if (math-matrixp arg)
- X (math-symb-map func 'elems (cdr (math-transpose arg)))
- X (math-symb-map func 'elems arg))
- X)
- X
- X(defun calcFunc-mapd (func arg)
- X (if (math-matrixp arg)
- X (math-symb-map func 'elems (cdr arg))
- X (math-symb-map func 'elems arg))
- X)
- X
- X
- X;;; "Reduce" a function over a vector (left-associatively). [O X V] [Public]
- X(defun math-reduce-vec (f a)
- X (if (math-vectorp a)
- X (if (cdr a)
- X (math-reduce-vec-step f (car (cdr a)) (cdr (cdr a)))
- X 0)
- X a)
- X)
- X
- X(defun math-reduce-vec-step (f tot a) ; [O X O L]
- X (if a
- X (math-reduce-vec-step f
- X (funcall f tot (car a))
- X (cdr a))
- X tot)
- X)
- X
- X;;; Reduce a function over the columns of matrix A. [V X V] [Public]
- X(defun math-reduce-cols (f a)
- X (if (math-matrixp a)
- X (cons 'vec (math-reduce-cols-col-step f (cdr a) 1 (length (nth 1 a))))
- X a)
- X)
- X
- X(defun math-reduce-cols-col-step (f a col cols)
- X (and (< col cols)
- X (cons (math-reduce-cols-row-step f (nth col (car a)) col (cdr a))
- X (math-reduce-cols-col-step f a (1+ col) cols)))
- X)
- X
- X(defun math-reduce-cols-row-step (f tot col a)
- X (if a
- X (math-reduce-cols-row-step f
- X (funcall f tot (nth col (car a)))
- X col
- X (cdr a))
- X tot)
- X)
- X
- X
- X;;; Reduce a function over a vector symbolically. [Public]
- X(defun calcFunc-reduce (func vec)
- X (if (math-matrixp vec)
- X (let (expr row)
- X (setq func (math-var-to-calcFunc func))
- X (or (math-vectorp vec)
- X (math-reject-arg vec 'vectorp))
- X (while (setq vec (cdr vec))
- X (setq row (car vec))
- X (while (setq row (cdr row))
- X (setq expr (if expr
- X (math-build-call func (list expr (car row)))
- X (car row)))))
- X (math-normalize expr))
- X (calcFunc-reducer func vec))
- X)
- X
- X(defun calcFunc-reducer (func vec)
- X (setq func (math-var-to-calcFunc func))
- X (or (math-vectorp vec)
- X (math-reject-arg vec 'vectorp))
- X (let ((expr (car (setq vec (cdr vec)))))
- X (or expr
- X (math-reject-arg vec "Vector is empty"))
- X (while (setq vec (cdr vec))
- X (setq expr (math-build-call func (list expr (car vec)))))
- X (math-normalize expr))
- X)
- X
- X(defun calcFunc-reducec (func vec)
- X (if (math-matrixp vec)
- X (calcFunc-reducer func (math-transpose vec))
- X (calcFunc-reducer func vec))
- X)
- X
- X(defun calcFunc-reducea (func vec)
- X (if (math-matrixp vec)
- X (cons 'vec
- X (mapcar (function (lambda (x) (calcFunc-reducer func x)))
- X (cdr vec)))
- X (calcFunc-reducer func vec))
- X)
- X
- X(defun calcFunc-reduced (func vec)
- X (if (math-matrixp vec)
- X (cons 'vec
- X (mapcar (function (lambda (x) (calcFunc-reducer func x)))
- X (cdr (math-transpose vec))))
- X (calcFunc-reducer func vec))
- X)
- X
- X
- X;;; Multiply matrix vector element lists A and B. [L L L]
- X(defun math-mul-mats (a b)
- X (and a
- X (cons (cons 'vec (math-mul-mat-row (car a) b))
- X (math-mul-mats (cdr a) b)))
- X)
- X
- X(defun math-mul-mat-row (a b) ; [L L L]
- X (if (math-no-empty-rows b)
- X (cons
- X (math-reduce-vec 'math-add
- X (math-map-vec-2 'math-mul
- X a
- X (cons 'vec (mapcar 'car b))))
- X (math-mul-mat-row a (mapcar 'cdr b)))
- X (if (math-list-all-nil b)
- X nil
- X (math-dimension-error)))
- X)
- X
- X(defun math-no-empty-rows (a) ; [P L]
- X (or (null a)
- X (and (consp (car a))
- X (math-no-empty-rows (cdr a))))
- X)
- X
- X(defun math-list-all-nil (a) ; [P L]
- X (or (null a)
- X (and (null (car a))
- X (math-list-all-nil (cdr a))))
- X)
- X
- X
- X;;; Return the number of elements in vector V. [Public]
- X(defun math-vec-length (v)
- X (if (math-vectorp v)
- X (1- (length v))
- X 0)
- X)
- X(fset 'calcFunc-vlen (symbol-function 'math-vec-length))
- X
- X;;; Get the Nth row of a matrix.
- X(defun math-mat-row (mat n)
- X (elt mat n)
- X)
- X
- X(defun calcFunc-mrow (mat n) ; [Public]
- X (and (integerp (setq n (math-check-integer n)))
- X (> n 0)
- X (math-vectorp mat)
- X (nth n mat))
- X)
- X
- X;;; Get the Nth column of a matrix.
- X(defun math-mat-col (mat n)
- X (cons 'vec (mapcar (function (lambda (x) (elt x n))) (cdr mat)))
- X)
- X
- X(defun calcFunc-mcol (mat n) ; [Public]
- X (and (integerp (setq n (math-check-integer n)))
- X (> n 0)
- X (math-vectorp mat)
- X (if (math-matrixp mat)
- X (and (< n (length (nth 1 mat)))
- X (math-mat-col mat n))
- X (nth n mat)))
- X)
- X
- X;;; Remove the Nth row from a matrix.
- X(defun math-mat-less-row (mat n)
- X (if (<= n 0)
- X (cdr mat)
- X (cons (car mat)
- X (math-mat-less-row (cdr mat) (1- n))))
- X)
- X
- X(defun calcFunc-mrrow (mat n) ; [Public]
- X (and (integerp (setq n (math-check-integer n)))
- X (> n 0)
- X (< n (length mat))
- X (math-mat-less-row mat n))
- X)
- X
- X;;; Remove the Nth column from a matrix.
- X(defun math-mat-less-col (mat n)
- X (cons 'vec (mapcar (function (lambda (x) (math-mat-less-row x n)))
- X (cdr mat)))
- X)
- X
- X(defun calcFunc-mrcol (mat n) ; [Public]
- X (and (integerp (setq n (math-check-integer n)))
- X (> n 0)
- X (if (math-matrixp mat)
- X (and (< n (length (nth 1 mat)))
- X (math-mat-less-col mat n))
- X (math-mat-less-row mat n)))
- X)
- X
- X(defun math-get-diag (mat) ; [Public]
- X (if (math-square-matrixp mat)
- X (cons 'vec (math-get-diag-step (cdr mat) 1))
- X (calc-record-why 'math-square-matrixp mat)
- X (list 'calcFunc-getdiag mat))
- X)
- X(fset 'calcFunc-getdiag (symbol-function 'math-get-diag))
- X
- X(defun math-get-diag-step (row n)
- X (and row
- X (cons (nth n (car row))
- X (math-get-diag-step (cdr row) (1+ n))))
- X)
- X
- X(defun math-transpose (mat) ; [Public]
- X (if (math-vectorp mat)
- X (if (math-matrixp mat)
- X (cons 'vec
- X (math-trn-step mat 1 (length (nth 1 mat))))
- X (math-col-matrix mat))
- X (and (math-numberp mat)
- X mat))
- X)
- X(fset 'calcFunc-trn (symbol-function 'math-transpose))
- X
- X(defun calcFunc-ctrn (mat)
- X (let ((trn (math-transpose mat)))
- X (and trn
- X (math-conj trn)))
- X)
- X
- X(defun math-trn-step (mat col cols)
- X (and (< col cols)
- X (cons (math-mat-col mat col)
- X (math-trn-step mat (1+ col) cols)))
- X)
- X
- X(defun math-arrange-vector (vec cols) ; [Public]
- X (if (and (math-vectorp vec) (integerp cols))
- X (let* ((flat (math-flatten-vector vec))
- X (mat (list 'vec))
- X next)
- X (if (<= cols 0)
- X (nconc mat flat)
- X (while (>= (length flat) cols)
- X (setq next (nthcdr cols flat))
- X (setcdr (nthcdr (1- cols) flat) nil)
- X (setq mat (nconc mat (list (cons 'vec flat)))
- X flat next))
- X (if flat
- X (setq mat (nconc mat (list (cons 'vec flat)))))
- X mat)))
- X)
- X(fset 'calcFunc-arrange (symbol-function 'math-arrange-vector))
- X
- X(defun math-flatten-vector (vec) ; [L V]
- X (if (math-vectorp vec)
- X (apply 'append (mapcar 'math-flatten-vector (cdr vec)))
- X (list vec))
- X)
- X
- X
- X;;; Copy a matrix. [Public]
- X(defun math-copy-matrix (m)
- X (if (math-vectorp (nth 1 m))
- X (cons 'vec (mapcar 'copy-sequence (cdr m)))
- X (copy-sequence m))
- X)
- X
- X;;; Convert a scalar or vector into an NxN diagonal matrix. [Public]
- X(defun math-diag-matrix (a &optional n)
- X (and n (not (integerp n))
- X (setq n (math-check-fixnum n)))
- X (if (math-vectorp a)
- X (if (and n (/= (length a) (1+ n)))
- X (list 'calcFunc-diag a n)
- X (if (math-matrixp a)
- X (if (and n (/= (length (elt a 1)) (1+ n)))
- X (list 'calcFunc-diag a n)
- X a)
- X (cons 'vec (math-diag-step (cdr a) 0 (1- (length a))))))
- X (if n
- X (cons 'vec (math-diag-step (make-list n a) 0 n))
- X (list 'calcFunc-diag a)))
- X)
- X(fset 'calcFunc-diag (symbol-function 'math-diag-matrix))
- X
- X(defun math-diag-step (a n m)
- X (if (< n m)
- X (cons (cons 'vec
- X (nconc (make-list n 0)
- X (cons (car a)
- X (make-list (1- (- m n)) 0))))
- X (math-diag-step (cdr a) (1+ n) m))
- X nil)
- X)
- SHAR_EOF
- echo "End of part 6"
- echo "File calc-ext.el is continued in part 7"
- echo "7" > s2_seq_.tmp
- exit 0
-